<script setup>
import { onMounted, ref, computed, nextTick } from 'vue';
import speakMessage from './components/speakMessage.vue';
import reply from './components/reply.vue';
import bottomBar from './components/bottomBar.vue';
import { getPostDetailApi } from '../../apis/postDetail';
import { useRoute, useRouter, onBeforeRouteUpdate, loadRouteLocation } from 'vue-router';
import { getCommentListApi, getPostLastCommentApi } from '@/apis/comment'
import { useUserStore } from '@/store/user'
import { ElMessage } from 'element-plus';
import { getPostIsGoodApi, switchGoodApi } from '@/apis/good'
import { getPostIsCollectionApi, switchCollectionApi } from '@/apis/collection'

const useStore = useUserStore()


const route = useRoute();
const router = useRouter();

// #region 电脑端分页代码

//当前页码
const currentPage = ref(1)
//当前页容量
const pageSize = ref(30)
// #region 电脑端分页代码
const messageRef = ref(null)
const handlePageChange = async (page) => {
  if (window.innerWidth > 800) {
    if (page) {
      currentPage.value = page
      sessionStorage.setItem('currentPage', page)

      await getCommentList(route.params.id, page)

    } else {
      console.log(currentPage.value);
      sessionStorage.setItem('currentPage', currentPage.value)

      await getCommentList(route.params.id, currentPage.value)

    }
  }

}

// #endregion


// #region 收藏代码
const isCollection = ref(false)


const shoucangColor = computed(() => {
  return isCollection.value ? '#FF4D4F' : '#999999'
})



// 切换收藏
const switchCollection = async () => {
  isCollection.value = !isCollection.value

  //发送请求修改后端的收藏
  const res = await switchCollectionApi(Number(route.params.id), useStore.userInfo.id, isCollection.value)

  //重新获取数据
  await getPostDetail()

  if (isCollection.value) {
    ElMessage.success(res.data)
  } else {
    ElMessage.info(res.data)
  }
}



const getPostIsCollection = async (postId, userId) => {
  const res = await getPostIsCollectionApi(postId, userId)
  isCollection.value = res.data
}


// #endregion



// #region 点赞代码
const isGood = ref(false)


const dianzanColor = computed(() => {
  return isGood.value ? 'red' : '#999999' //点赞颜色
})

// 切换点赞
const switchGood = async () => {
  isGood.value = !isGood.value

  //发送请求修改后端的点赞
  const res = await switchGoodApi(Number(route.params.id), useStore.userInfo.id, isGood.value)
  //重新获取数据
  await getPostDetail()

  if (isGood.value) {
    ElMessage.success(res.data)
  } else {
    ElMessage.info(res.data)
  }
}


// 传递postId和userId，获取该帖子被改用户点赞了
const getPostIsGood = async (postId, userId) => {
  const res = await getPostIsGoodApi(postId, userId)
  isGood.value = res.data
}

// #endregion



// #region 手机端代码

// 无限滚动
async function scroll() {
  //无限滚动只适配手机端
  if (window.innerWidth < 800) {
    if (hasMoreData()) {
      currentPage.value += 1
      await getPhoneCommentList(route.params.id, currentPage.value)
    }
  }
}

// 判断是否需要加载更多数据
const hasMoreData = () => {
  const loadedDataCount = currentPage.value * pageSize.value; // 已加载的数据条数
  return loadedDataCount < commentTotal.value; // 是否还有更多数据可以加载
};


//手机端：测试点击内容直接唤醒下面的回复组件
const clickMessage = (event, content, commentId, userId, getAdditionalCommentList) => {
  //因为回复和回帖都是同一个组件,应该有另一个组件来区分
  /* 只有手机端才能触发 */


  if (window.innerWidth < 768) {
    bottomRef.value.isFocus(content, commentId, userId, getAdditionalCommentList);
    /* 阻止冒泡 */
    event.stopPropagation();
  }

}





// 手机端,点击整个帖子区域，都会触发的函数
const clickPostContainer = () => {

  if (window.innerWidth < 768) {
    bottomRef.value.isClickContainer = false;
    bottomRef.value.inputRef.blur();
  }
}


//手机端 ，删除评论，因为手机端是一个数组，所以需要删除数组中的元素
const phoneDeleteComment = (commentId) => {
  console.log(commentId);
  const index = commentList.value.findIndex(item => item.commentId === commentId)
  commentList.value.splice(index, 1)
}

//手机端 ，添加评论，因为手机端是一个数组，所以需要添加数组中的元素
const phoneAddComment = async () => {

  /* 分两种情况。在最后一页和不在最后一页 */

  const totalPages = Math.ceil(commentTotal.value / pageSize.value);
  console.log(totalPages);


  if (currentPage.value === totalPages) {

    console.log('最后一页');


    /* 拿到该帖子的最后一条评论，插入到数组中 */
    const res = await getPostLastCommentApi({ postId: route.params.id })

    commentList.value.push(res.data)
  } else {
    /* 不在最后一页，什么都不做，它到最后会自动加载 */
    console.log('不在最后一页');
  }





}

// #endregion


// #region 传递一个commentId参数，页面滚动到对应的评论
const scrollToCommentId = (commentId, additionalCommentId) => {
  const element = document.getElementById(`commentId-${commentId}`);
  /* 如果没有追评id */

  if (element) {
    console.log(element);

    commentScroll(element, additionalCommentId);

  } else {
    // 如果元素不在当前页面，进行页面加载
    loadPage(commentId, additionalCommentId);

  }
};


/* 加载下一页 */
const loadPage = async (commentId, additionalCommentId) => {
  // 假设这里是加载新页面的逻辑
  /* 判断是不是最后一页了 */
  const totalPages = Math.ceil(commentTotal.value / pageSize.value);
  console.log(totalPages);

  if (currentPage.value === totalPages) {
    return;
  }

  await handlePageChange(currentPage.value + 1)

  setTimeout(() => {

    const element = document.getElementById(`commentId-${commentId}`);

    if (element) {
      commentScroll(element, additionalCommentId);
    } else {
      // 如果元素不在当前页面，进行页面加载
      loadPage(commentId, additionalCommentId);
    }
  }, 100)

};


/* 页面滚动的代码 */
const commentScroll = (element, additionalCommentId) => {

  setTimeout(() => {
    // 如果元素在当前页面，直接滚动
    window.scrollTo({
      top: element.offsetTop - 200,
      // top: element.offsetTop,
      behavior: "smooth"
    });
  }, 500)

  // 如果有追评id,那就调用追评的方法
  if (!additionalCommentId) {
    highlightElement(element);
  } else {
    //如果有追评id,那就调用追评的方法

    scrollToAdditionalCommentId(additionalCommentId, element);
  }

}


/* 找到元素就高亮显示 */
const highlightElement = (element) => {
  element.style.background = 'rgba(135, 206, 235, 0.2)';
  setTimeout(() => {
    element.style.background = 'rgba(255, 255, 255, 0.5)';
  }, 2000);
};

// #endregion



// #region 传递一个additionalCommentId参数，页面滚动到对应的评论

const scrollToAdditionalCommentId = (additionalCommentId, element) => {

  setTimeout(() => {

    /* 获得评论底下的按钮,模拟点击,打开回复列表 */
    clickButton(element)


    /* 拿到追评元素 */
    const replyElement = document.getElementById(`reply-${additionalCommentId}`);
    if (replyElement) {

      scrollFangFa(replyElement)

    } else {
      /* 如果元素不在当前页面，进行页面加载 */


      clickNextPage(element, additionalCommentId)
    }
  }, 100);
}


/* 模拟点击下一页的按钮 */
const clickNextPage = (element, additionalCommentId) => {
  console.log(element);

  setTimeout(() => {
    // 获取按钮元素
    const button = element.querySelector('.btn-next.is-last');

    // 如果元素存在，则模拟点击
    if (button) {
      button.click();
      setTimeout(() => {
        // 拿到追评元素
        const replyElement = document.getElementById(`reply-${additionalCommentId}`);
        if (replyElement) {
          scrollFangFa(replyElement)
        } else {


          if (button.getAttribute('aria-disabled') === "false") {
            /* 如果元素不在当前页面，进行页面加载 */
            clickNextPage(element, additionalCommentId)
          } else {
            /* 如果元素不在当前页面，但是已经到了最后一页了,那么就还原按钮的样式 */
            /* 将回复框收起来 */
            setTimeout(() => {
              clickButton(element)
            }, 100);

          }
        }
      }, 100)

    }

  }, 100)


}



const clickButton = (element) => {


  /* 拿到评论底下的按钮 */
  const button = element.querySelector('button.need-left-margin.blue');



  if (button) {
    // 模拟点击按钮
    setTimeout(() => {
      button.click()
    }, 500);
  }
}


const scrollFangFa = throttle((replyElement) => {
  console.log(replyElement);


  setTimeout(() => {
    const scrollY = replyElement.getBoundingClientRect().top + window.scrollY - 300; // 滚动到这个位置

    window.scrollTo({
      top: scrollY,
      behavior: "smooth"
    });

  }, 500)

  replyElement.style.background = 'rgba(135, 206, 235, 0.2)';
  setTimeout(() => {
    replyElement.style.background = 'rgba(255, 255, 255, 0.5)';
  }, 1500);
}, 2000); // 2秒间隔


/* 节流防止多次滚动 */
function throttle(func, limit) {
  let lastFunc;
  let lastRan;

  return function (...args) {
    if (!lastRan) {
      func.apply(this, args);
      lastRan = Date.now();
    } else {
      clearTimeout(lastFunc);
      lastFunc = setTimeout(() => {
        if ((Date.now() - lastRan) >= limit) {
          func.apply(this, args);
          lastRan = Date.now();
        }
      }, limit - (Date.now() - lastRan));
    }
  };
}


// #endregion



// #region 获取数据


// 获取评论列表

const commentList = ref([])
const commentTotal = ref(0)
/* 电脑端分页 */
const getCommentList = async (postId = route.params.id, currentPage = 1) => {

  const res = await getCommentListApi({ postId, currentPage })
  commentList.value = res.records
  commentTotal.value = res.total
}

/* 手机端分页应该要直接Push到数组里 */
const getPhoneCommentList = async (postId = route.params.id, currentPage = 1) => {

  const res = await getCommentListApi({ postId, currentPage })
  commentList.value.push(...res.records);
  commentTotal.value = res.total
}


// 获得帖子详情
const postDetailData = ref({})
const getPostDetail = async (postId = route.params.id, userId = useStore.userInfo.id) => {

  const res = await getPostDetailApi(postId, userId)
  postDetailData.value = res.data
}

// #endregion





// 路由切换时重新获取数据
onBeforeRouteUpdate(async (to) => {

  await getPostDetail(to.params.id)
  await getCommentList(to.params.id, 1)

  //当切换新的帖子时，将分页的当前页码置为1
  sessionStorage.setItem('currentPage', 1)

  //获得是否收藏和是否点赞



})


// 底部栏组件实例
const bottomRef = ref(null)


onMounted(async () => {

  //获得帖子详情
  try {
    await getPostDetail()
  } catch (error) {
    // 返回到前一个页面
    if (window.history.length > 1) {
      router.go(-1);
    } else {
      //三秒后关闭当前页面
      ElMessage.error('将在三秒后关闭当前页面');
      setTimeout(() => {
        window.close();
      }, 3000);
    }
    return; // 确保后续代码不再执行
  }
  //获得评论列表
  await getCommentList(route.params.id, 1)
  //当进到一个新的帖子时，将分页的当前页码置为1
  sessionStorage.setItem('currentPage', 1)


  //获得是否点赞了
  getPostIsGood(route.params.id, useStore.userInfo.id)

  //获得是否收藏了
  getPostIsCollection(route.params.id, useStore.userInfo.id)



  /* 点击消息组件中的内容时，跳转过来时需要跳转到楼层 */
  const commentId = route.query.commentId;// 获取传递的 commentId 参数
  const additionalCommentId = route.query.additionalCommentId; // 获取传递的 additionalCommentId 参数

  /* 先判断有没有 追评id */
  if (additionalCommentId) {


    // 确保 DOM 元素已经渲染后再调用 scrollToCommentId
    setTimeout(() => {
      scrollToCommentId(commentId, additionalCommentId);
    }, 100);


    /* 如果没有追评Id,就判断有没有评论id */
  } else if (commentId) {
    setTimeout(() => {
      scrollToCommentId(commentId)
    }, 100);


  }



})


</script>


<!-- 贴吧是外面为紧凑排列，把换行取消。帖子里面正常显示 -->
<template>

  <div class="post-detail-container" v-infinite-scroll="scroll" @click="clickPostContainer">
    <!-- 用一个表来存储这些记录，直接for渲染即可了。把回复当作组件。直接渲染 -->
    <div class="title">
      <span>{{ postDetailData.title }}</span>
    </div>
    <div class="info">
      <span class="need-margin-left"> {{ postDetailData.categoryName }} </span>
      <span class="need-margin-left"><svg-icon class="icon" name="shizhong" />{{ postDetailData.publishTime }}</span>
      <span class="need-margin-left"><svg-icon class="icon" name="yanjing" /> {{ postDetailData.readNumber }}</span>

      <!-- 收藏和点赞点击时切换svg -->
      <span class="need-margin-left"><svg-icon @Click="switchCollection" class="icon" :fill="shoucangColor"
          name="shoucang" />
        {{ postDetailData.collectionNumber || 0 }}
      </span>
      <span class="need-margin-left"><svg-icon @Click="switchGood" class="icon" :fill="dianzanColor" name="dianzan" />
        {{ postDetailData.goodNumber || 0 }}</span>
      <span class="need-margin-left"><svg-icon class="icon" name="huifu" />
        {{ postDetailData.replyNumber || 0 }}
      </span>
    </div>

    <div class="content">
      <p>帖子主题</p>
      {{ postDetailData.content }}
      <div class="preview">
        <div class="preview-card" v-if="postDetailData.imgList !== []">
          <el-image v-for="item in postDetailData.imgList" :key="item" :src="item" fit="contain" width="100px"
            :preview-src-list="[item]" hide-on-click-modal="true"></el-image>
        </div>
        <div class="preview-mask"></div>
      </div>
    </div>

    <!-- 在这里动态的计算出组件遇到的高度. 好像也不用.直接内容撑开就好了.因为这里不用动态的伸缩div-->
    <speakMessage v-if="commentList" v-for="item in commentList" :key="item.commentId" :commentData="item"
      :getCommentList="getCommentList" :getPostDetail="getPostDetail" class="message" :clickMessage="clickMessage"
      :phoneDeleteComment="phoneDeleteComment" ref="messageRef" :id="'commentId-' + item.commentId" />
    <div v-else>
      <el-empty :image-size="300" description="暂无评论" />
    </div>


    <!-- 分页组件 -->
    <div v-if="commentList !== []" class="paging hidden-md-and-down">
      <el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :disabled="disabled" background
        layout="prev, pager, next,jumper" :total="commentTotal" @change="handlePageChange" />
      <div class="need-margin-left hidden-md-and-down">
      </div>
    </div>

    <!-- 倒底了的内容 -->
    <div class="data-empty hidden-md-and-up">
      <span>已加载全部回复</span>
    </div>


    <!-- 回复组件 -->
    <reply :currentPage="currentPage" :getCommentList="getCommentList" :getPostDetail="getPostDetail"
      class="reply hidden-md-and-down"></reply>

    <div style="height: 100px;"> <!-- 留白 --></div>

    <!-- 页面最底部信息组件 -->
    <foot-info class="foot hidden-md-and-down"></foot-info>


  </div>

  <!-- 底部栏 -->
  <bottomBar style="font-size: 1.6rem;" ref="bottomRef" class="hidden-md-and-up" :getCommentList="getCommentList"
    :getPostDetail="getPostDetail" :phoneAddComment="phoneAddComment">
  </bottomBar>




</template>

<style lang='scss' scoped>
// 公用的

.need-margin-left {
  margin-left: 20px;
}

// 电脑端样式
@media screen and (min-width: 768px) {
  .post-detail-container {
    margin: 50px auto 0;
    font-size: 1.6rem;
    width: $base-container-width;
    background-color: white;
    min-height: 1000px;


    .title {
      padding: 20px;
      font-size: 24px;
      font-weight: bold;
      //强制换行
      word-break: break-all;
    }

    .info {
      width: calc($base-container-width - 100px);
      margin: 0 auto;
      background-image: linear-gradient(0deg, rgba(207, 217, 223, 0.2) 0%, rgba(226, 235, 240, 0.2) 100%);
      height: 50px;
      line-height: 50px;
      margin-bottom: 50px;
      font-size: 1.8rem;

      .icon {
        vertical-align: middle;
        margin-bottom: 4px;

        &:hover {
          cursor: pointer;
        }
      }




    }

    /* 帖子内容区 */
    .content {
      border: 1px solid #ccc;
      min-height: 100px;
      padding-left: 40px;


      & p {
        color: red;
        margin-bottom: 10px;
      }
    }

    .paging {
      display: flex;
      align-items: center;
      margin: 40px 0 0 400px;


      .reply-number {
        color: rgb(252, 73, 13);
      }
    }

    .reply {
      // height: 500px;
      width: 90%;
      margin: 50px auto 0;
      // padding-bottom: 50px;
    }

    .foot {
      height: 50px;
    }
  }
}

// 移动端样式
@media screen and (max-width: 768px) {
  .post-detail-container {
    margin-top: 50px;
    font-size: 2rem;
    width: 100vw;
    background-color: white;
    // border: 1px solid red;



    .title {
      width: 100vw;
      font-weight: bold;
      // 强制换行
      word-break: break-all;
      /* 添加居中对齐 */
      text-align: center;
      padding: 10px;
    }

    .info {
      width: 100vw;
      font-size: 1.1rem;
      margin: 0 auto;
      background-image: linear-gradient(0deg, rgba(207, 217, 223, 0.2) 0%, rgba(226, 235, 240, 0.2) 100%);
      height: 50px;
      line-height: 50px;
      margin-bottom: 20px;

      .icon {
        vertical-align: middle;
        margin-bottom: 4px;

      }

    }

    .content {
      padding: 10px;
      border: 1px solid #ccc;
      border-radius: 10px;
      margin-bottom: 20px;

      & p {
        color: red;
      }
    }

    .paging {
      margin-top: 20px;
    }

    .data-empty {
      margin-bottom: 80px;
      margin-top: 20px;
      text-align: center;
      color: $no-highlight-color;
    }

    .reply {
      height: 550px;
      width: 90vw;
      margin: 50px auto;
      // margin-top: 50px;
    }

    .foot {
      height: 50px;
    }
  }
}
</style>